//
//  BaseDao.swift
//  SimpleCal
//
//  Created by 杜晓祥 on 2021/11/2.
//

import Foundation
import CoreData
import Cocoa

class BaseDao<T: NSManagedObject> {
    /**
     获取泛型类名称
     */
    private var className: String {
        let fullName = NSStringFromClass(T.self)
        let range = fullName.range(of: ".")
        if let range = range {
            return String(fullName.suffix(from: range.upperBound))
        }
        return fullName
    }
    /**
     保存数据
     --parameter: completion实体类数据填充
     */
    func save(completionHandler completion: ((_ type:T) -> Void)) {
        let app = NSApplication.shared.delegate as! AppDelegate
        let context = app.persistentContainer.viewContext
        let t = NSEntityDescription.insertNewObject(forEntityName: className, into: context) as! T
        completion(t)
        do {
            try context.save()
            print("保存成功")
        } catch {
            return
        }
    }
    
    func query (format:String)-> [T] {
        let app = NSApplication.shared.delegate as! AppDelegate
        let context = app.persistentContainer.viewContext
        
        let fetchRequest = NSFetchRequest<T>(entityName: className)
        fetchRequest.fetchLimit = 10
        fetchRequest.fetchOffset = 0
        let predicate = NSPredicate(format: "name !=''", "")
        fetchRequest.predicate = predicate
        do {
            let fetchedObjects = try context.fetch(fetchRequest)
            return fetchedObjects
        } catch {
            return [T]()
        }
    }
    
    func query() -> BaseQueryBuild {
        let app = NSApplication.shared.delegate as! AppDelegate
        let context = app.persistentContainer.viewContext
        let fetchRequest = NSFetchRequest<T>(entityName: className)
        return BaseQueryBuild(request: fetchRequest, context: context)
    }
    
    class BaseQueryBuild {
        private var fetchRequest:NSFetchRequest<T>
        private var context:NSManagedObjectContext
        fileprivate init(request:NSFetchRequest<T>, context:NSManagedObjectContext) {
            self.fetchRequest = request
            self.context = context
        }
        func limit(i:Int, n:Int) -> BaseQueryBuild {
            fetchRequest.fetchLimit = n
            fetchRequest.fetchOffset = i
            return self
        }
        func predicate(format:String, _ args:CVarArg...) -> BaseQueryBuild {
            let p = NSPredicate(format: format, args)
            fetchRequest.predicate = p
            return self
        }
        
        func sort(key:String, ascending:Bool) -> BaseQueryBuild {
            let s = NSSortDescriptor(key: key, ascending: ascending)
            let ss = [s]
            fetchRequest.sortDescriptors = ss
            return self
        }
        
        func build() -> [T] {
            do {
                let fetchObjects = try context.fetch(fetchRequest)
                return fetchObjects
            } catch {
                return [T]()
            }
        }
    }
    
}
